import numpy as np

"""
碰撞检测器
"""


class Collider:
    def __init__(self, min_pos, max_pos):
        self.center_pos = None
        self.min_pos, self.max_pos = min_pos, max_pos

    def set_position(self, position):
        self.center_pos = position

    def contains(self, point):
        return (self.min_pos[0] <= point[0] <= self.max_pos[0] and
                self.min_pos[1] <= point[1] <= self.max_pos[1] and
                self.min_pos[2] <= point[2] <= self.max_pos[2])

    def intersects(self, other):
        """
        检测当前 AABB 是否与另一个 AABB 相交
        :param other: 另一个 AABB 对象
        :return: 如果相交返回 True，否则返回 False
        """
        # 检查每个轴上的重叠情况
        return (self.min_pos[0] <= other.max_pos[0] and
                self.max_pos[0] >= other.min_pos[0] and
                self.min_pos[1] <= other.max_pos[1] and
                self.max_pos[1] >= other.min_pos[1] and
                self.min_pos[2] <= other.max_pos[2] and
                self.max_pos[2] >= other.min_pos[2])

    def block_collision_processor(self, block_colliders, player_velocity):
        dx, dy, dz = player_velocity[0], player_velocity[1], player_velocity[2]
        on_ground = False

        x_aabb = Collider(self.min_pos + np.array([dx, 0, 0], dtype=np.float32), self.max_pos + np.array([dx, 0, 0], dtype=np.float32))
        for block_collider in block_colliders:
            if x_aabb.intersects(block_collider):
                player_velocity[0] = 0
                break

        y_aabb = Collider(self.min_pos + np.array([0, dy, 0], dtype=np.float32), self.max_pos + np.array([0, dy, 0], dtype=np.float32))
        for block_collider in block_colliders:
            if y_aabb.intersects(block_collider):
                player_velocity[1] = 0
                on_ground = dy < 0
                break

        z_aabb = Collider(self.min_pos + np.array([0, 0, dz], dtype=np.float32), self.max_pos + np.array([0, 0, dz], dtype=np.float32))
        for block_collider in block_colliders:
            if z_aabb.intersects(block_collider):
                player_velocity[2] = 0
                break

        return player_velocity, on_ground


class Ray:
    def __init__(self, origin, direction):
        self.origin = origin
        self.direction = direction
        self.t_min = 0.0
        self.t_max = float('inf')

    def intersects_aabb_point(self, other):

        for i in range(3):
            if abs(self.direction[i]) < 1e-6:
                if self.origin[i] < other.min_pos[i] or self.origin[i] > other.max_pos[i]:
                    return None
            else:
                ood = 1.0 / self.direction[i]
                t1 = (other.min_pos[i] - self.origin[i]) * ood
                t2 = (other.max_pos[i] - self.origin[i]) * ood
                if t1 > t2:
                    t1, t2 = t2, t1
                self.t_min = max(self.t_min, t1)
                self.t_max = min(self.t_max, t2)

                if self.t_min > self.t_max:
                    return None

        point = self.origin + self.direction * self.t_min
        return point
